class Type:
    def __eq__(self, othertype):
        return othertype.__class__ == self.__class__

class Integer(Type):
    pass

class Real(Type):
    pass

class Rational(Type):
    pass

class Matrix(Type):
    pass

class Array(Type):
    def __init__(self, holdtype):
        assert(isinstance(holdtype, Type))
        assert(holdtype.__class__ != Matrix)
        self._holdtype = holdtype
    def __eq__(self, othertype):
        if not Type.__eq__(self, othertype):
            return False
        return self._holdtype == othertype._holdtype

class Restricted(Type):
    def __init__(self, basetype, minvalue, maxvalue):
        assert(isinstance(holdtype, Type))
        assert(basetype.__class__ != Matrix)
        assert(basetype.__class__ != Array)
        self._basetype = basetype
        self._minvalue = minvalue
        self._maxvalue = maxvalue
    def __eq__(self, othertype):
        if not Type.__eq__(self, othertype):
            return False
        return (self._basetype == othertype._basetype) and (self._minvalue == othertype._minvalue) and (self._maxvalue == othertype._maxvalue)

class Enum(Type):
    def __init__(self, name, idlist):
        self._name = name
        self._idlist = idlist
    def __eq__(self, othertype):
        if not Type.__eq__(self, othertype):
            return False
        return self._idlist == othertype._idlist

class Struct(Type):
    def __init__(self, name, elemlist):
        self._name = name
        self._elemlist = elemlist
    def __eq__(self, othertype):
        if not Type.__eq__(self, othertype):
            return False
        return self._elemlist == othertype._elemlist
